package com.knowledge.common;

/**
 * @author: zhaoyongke
 * @create: 2025-03-18 11:25
 * @description: AliyunOssUploadUtils
 */

import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.*;
import com.knowledge.common.config.AliyunOssConfig;
import com.knowledge.common.core.domain.AjaxResult;
import com.knowledge.common.utils.file.FileUploadUtils;
import com.knowledge.common.utils.uuid.IdUtils;
import com.knowledge.common.utils.uuid.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;

/**
 * @author zouhuu
 * @description 阿里云对象存储上传工具类
 * @date 2022/06/16 14:21:12
 */
@Component
public class AliyunOssUploadUtils {

    private static AliyunOssConfig aliyunOssConfig;


    /**
     * 使用构造方法注入配置信息
     */
    @Autowired
    public AliyunOssUploadUtils(AliyunOssConfig aliyunOssConfig) {
        AliyunOssUploadUtils.aliyunOssConfig = aliyunOssConfig;
    }

    /**
     * 上传文件
     *
     * @param file
     * @return
     * @throws Exception
     */
    public static String uploadFile(MultipartFile file) throws Exception {

        // 生成 OSSClient
        OSS ossClient = new OSSClientBuilder().build(aliyunOssConfig.getEndpoint(), aliyunOssConfig.getAccessKeyId(), aliyunOssConfig.getAccessKeySecret());
        // 原始文件名称
        // String originalFilename = file.getOriginalFilename();
        // 编码文件名
        String fileName = FileUploadUtils.extractFilename(file);
        // 过滤特殊字符 - 只保留字母、数字、点、下划线和连字符
        fileName = IdUtils.simpleUUID() + "_" + fileName.replaceAll("[^a-zA-Z0-9._-]", "");
        // 文件路径名称
        String filePathName = aliyunOssConfig.getFilehost() + "/" + fileName;
        try {
            ossClient.putObject(aliyunOssConfig.getBucketName(), filePathName, file.getInputStream());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return aliyunOssConfig.getUrl() + "/" + filePathName;
    }

    public static String uploadDocumentFile(MultipartFile file, String zskId, String documentId) throws Exception {

        // 生成 OSSClient
        OSS ossClient = new OSSClientBuilder().build(aliyunOssConfig.getEndpoint(), aliyunOssConfig.getAccessKeyId(), aliyunOssConfig.getAccessKeySecret());
        // 原始文件名称
        // String originalFilename = file.getOriginalFilename();
        // 编码文件名
        String fileName = FileUploadUtils.extractFilename(file);
        // 过滤特殊字符 - 只保留字母、数字、点、下划线和连字符
        fileName = IdUtils.simpleUUID() + "_" + fileName.replaceAll("[^a-zA-Z0-9._-]", "");
        // 文件路径名称
        String filePathName = zskId + "/" + documentId + "/" + fileName;
        try {
            ossClient.putObject(aliyunOssConfig.getBucketName(), filePathName, file.getInputStream());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return aliyunOssConfig.getUrl() + "/" + filePathName;


    }

    public static String uploadImageToOss(byte[] imageBytes, String objectKeyPrefix) {
        // 生成唯一的对象键
        String objectKey = objectKeyPrefix + UUID.randomUUID().toString() + ".png";

        // 创建OSSClient实例
        OSS ossClient = new OSSClientBuilder().build(aliyunOssConfig.getEndpoint(), aliyunOssConfig.getAccessKeyId(), aliyunOssConfig.getAccessKeySecret());

        try {
            // 上传文件
            ossClient.putObject(aliyunOssConfig.getBucketName(), objectKey, new ByteArrayInputStream(imageBytes));
            return aliyunOssConfig.getUrl() + "/" + objectKey;
        } finally {
            // 关闭OSSClient
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    public static void deleteFileByForder(String forder) {
        // 填写Bucket名称，例如examplebucket。
        String bucketName = aliyunOssConfig.getBucketName();
        // 如果您需要删除所有前缀为src的文件，则prefix设置为src。设置为src后，所有前缀为src的非目录文件、src目录以及目录下的所有文件均会被删除。
        String prefix = forder;
        // 创建OSSClient实例。
        // 当OSSClient实例不再使用时，调用shutdown方法以释放资源。
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);

        OSS ossClient = new OSSClientBuilder().build(aliyunOssConfig.getEndpoint(), aliyunOssConfig.getAccessKeyId(), aliyunOssConfig.getAccessKeySecret());
        try {
            // 列举所有包含指定前缀的文件并删除。
            String nextMarker = null;
            ObjectListing objectListing = null;
            do {
                ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName)
                        .withPrefix(prefix)
                        .withMarker(nextMarker);

                objectListing = ossClient.listObjects(listObjectsRequest);
                if (objectListing.getObjectSummaries().size() > 0) {
                    List<String> keys = new ArrayList<>();
                    for (OSSObjectSummary s : objectListing.getObjectSummaries()) {
                        System.out.println("key name: " + s.getKey());
                        keys.add(s.getKey());
                    }
                    DeleteObjectsRequest deleteObjectsRequest = new DeleteObjectsRequest(bucketName).withKeys(keys).withEncodingType("url");
                    DeleteObjectsResult deleteObjectsResult = ossClient.deleteObjects(deleteObjectsRequest);
                    List<String> deletedObjects = deleteObjectsResult.getDeletedObjects();
                    try {
                        for (String obj : deletedObjects) {
                            String deleteObj = URLDecoder.decode(obj, "UTF-8");
                            System.out.println(deleteObj);
                        }
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                }

                nextMarker = objectListing.getNextMarker();
            } while (objectListing.isTruncated());
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    /**
     * 从OSS下载文件
     *
     * @param fileName 文件名
     * @return 文件字节数组
     * @throws Exception 下载异常
     */
    public static byte[] downloadFile(String fileName) throws Exception {
        // 生成 OSSClient
        OSS ossClient = new OSSClientBuilder().build(
                aliyunOssConfig.getEndpoint(),
                aliyunOssConfig.getAccessKeyId(),
                aliyunOssConfig.getAccessKeySecret()
        );

        try {
            // 处理文件路径：如果fileName已经是完整URL，则提取相对路径部分
            String filePathName;
            if (fileName.startsWith("http")) {
                // 提取相对路径部分（去掉域名前缀）
                String urlPrefix = aliyunOssConfig.getUrl() + "/";
                if (fileName.startsWith(urlPrefix)) {
                    filePathName = fileName.substring(urlPrefix.length());
                } else {
                    // 如果不是标准格式，尝试从最后一个斜杠后提取
                    int lastSlashIndex = fileName.lastIndexOf('/');
                    filePathName = fileName.substring(lastSlashIndex + 1);
                }
            } else {
                // 构造完整的文件路径
                filePathName = aliyunOssConfig.getFilehost() + "/" + fileName;
            }

            // 下载文件
            OSSObject ossObject = ossClient.getObject(aliyunOssConfig.getBucketName(), filePathName);

            // 读取文件内容为字节数组
            byte[] bytes = ossObject.getObjectContent().readAllBytes();

            return bytes;
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}

